CloudFormationとAWS CLIで作るCodeDeploy(Blue/Green)環境
こんにちは、坂巻です。
CodeDeploy(Blue/Green)動作検証用の環境がほしく、構築しましたのでアウトプットしておきます。
はじめに
Auto Scalingで使用するAMIはPackerで作成し、AWSの各種サービスはCloudFormation、スタックの作成等にAWS CLIを利用しています。CloudFormation、Packerのテンプレート、CodeDeploy AppSpec File等は、GitHubに格納していますので、こちらを利用し構築していきます。
上記を任意のディレクトリに保存します。テンプレート等を格納したファイルは以下の構成になっています。
$ tree . ├── cloudformation │ └── template.yml ├── codedeploy │ ├── app │ │ └── index.html │ └── appspec.yml └── packer ├── scripts │ ├── codedeploy.sh │ └── httpd.sh └── template.json
目次
- 構成
- 環境構築
- AMI作成
- スタック作成
- デプロイグループ作成
- リビジョン作成/アップロード
- デプロイ実行
構成
構築する構成のイメージは以下となります。構築後はBlue/GreenデプロイにてEC2上のWebコンテンツを置き換えたいと思います。
環境構築
AMI作成
Packerにてゴールデンイメージを作成します。最新のAmazon Linux 2に、CodeDeployエージェント、Apacheをインストールします。処理の詳細はtemplate.json
をご確認ください。なお、CodeDeployエージェントのインストールは、公式ドキュメントにしたがっています。
作成するAMI名は任意の名称でtemplate.json
に、コマンドライン引数にて受け渡すようにしてあります。本エントリでは、受け渡す値は環境変数を利用したいと思います。
$ AMI_NAME=GoldenYotsugi $ echo ${AMI_NAME} GoldenYotsugi
packer
ディレクトリに移動し、テンプレートの書式をチェックします。
$ cd packer $ packer validate -var ami-name=${AMI_NAME} template.json Template validated successfully.
ビルドします。
$ packer build -var ami-name=${AMI_NAME} template.json amazon-ebs output will be in this color. ==> amazon-ebs: Prevalidating AMI Name: test-yotsugi amazon-ebs: Found Image ID: ami-0f9ae750e8274075b (省略) Build 'amazon-ebs' finished. ==> Builds finished. The artifacts of successful builds are: --> amazon-ebs: AMIs were created: ap-northeast-1: ami-0ca082db551b278cb
ビルドが正常に終了すると、AMIのIDが出力されます。こちらのIDは後続で使用するので、環境変数にセットしておきます。
LAUNCH_CONFIG_IMAGE_ID=`aws ec2 describe-images \ --filters "Name=tag-key,Values=Name" Name=tag-value,Values=${AMI_NAME} | jq -r '.Images[].ImageId'`
ビルド結果に出力されたAMI IDと同様か確認してください。
$ echo ${LAUNCH_CONFIG_IMAGE_ID} ami-0ca082db551b278cb
スタック作成
作成するスタック名、テンプレートファイルのパス、テンプレート名を環境変数にセットします。
STACK_NAME=CodeDeployAppStack TEMPLATE_DIR=../cloudformation/ TEMPLATE_NAME=template.yml
セットした内容を確認します。
cat << ETX STACK_NAME : ${STACK_NAME} TEMPLATE_DIR : ${TEMPLATE_DIR} TEMPLATE_NAME : ${TEMPLATE_NAME} ETX
CloudFormationスタックを作成します。 このテンプレートは、スタック作成時に以下パラメーターの入力が必要になります。
パラメーター名 | 説明 |
---|---|
projectName | 各種AWSリソースに付与する任意の名称(prefixとして利用) |
eC2KeyPair | EC2で使用するキーペアを指定(事前に作成が必要) |
launchConfigImageId | Launch Configに指定するAMI ID(先程作成したAMI ID) |
snsSubscription | SNSサブスクリプションに設定するEmailアドレス |
上記、パラメーターに指定する値を環境変数にセットします。
PROJECT_NAME=test-yotsugi EC2_KEY_PAIR=test-yotsugi-key [email protected]
セットした内容を確認します。
cat << ETX EC2_KEY_PAIR : ${EC2_KEY_PAIR} PROJECT_NAME : ${PROJECT_NAME} SNS_SUBSCRIPTION : ${SNS_SUBSCRIPTION} ETX
スタックを作成します。必要な値は、環境変数にセットされているので、以下のコマンドのまま実行できます。
aws cloudformation create-stack \ --stack-name ${STACK_NAME} \ --template-body file://${TEMPLATE_DIR}${TEMPLATE_NAME} \ --parameters \ ParameterKey=eC2KeyPair,ParameterValue=${EC2_KEY_PAIR} \ ParameterKey=launchConfigImageId,ParameterValue=${LAUNCH_CONFIG_IMAGE_ID} \ ParameterKey=projectName,ParameterValue=${PROJECT_NAME} \ ParameterKey=snsSubscription,ParameterValue=${SNS_SUBSCRIPTION} \ --capabilities 'CAPABILITY_NAMED_IAM'
コマンドが正常に実行されるとStackId
が出力されます。
{ "StackId": "arn:aws:cloudformation:ap-northeast-1:XXXXXXXXXXXX:stack/CodeDeployAppStack/28a0e190-5e44-11e9-bd44-0e89097244e0" }
スタックの作成が完了したことを確認します。
$ aws cloudformation describe-stacks --stack-name ${STACK_NAME} | jq '.Stacks[].StackStatus' "CREATE_COMPLETE"
なお、スタックが作成中の場合はCREATE_IN_PROGRESS
となります。正常に完了した場合は、SNSより指定したアドレスに、サブスクリプションの確認メールが送付されているので適宜有効化してください。
デプロイグループ作成
現時点では、EC2 Auto ScalingのBlue/Greenデプロイについては、CloudFormationではサポートされていないようです。
注記 Blue/Green デプロイは、AWS CloudFormation では AWS Lambda コンピューティングプラットフォームでのみサポートされます。
デプロイグループの作成はAWS CLIを利用します。作成に必要な情報を環境変数にセットします。
- GROUP_NAME…作成する任意のデプロイグループ名
- APP_NAME…CodeDeployアプリケーション名(このまま入力)
- ROLE_ARN…CodeDeployサービスロールのARN(このまま入力)
- ASG_NAME…デプロイ対象のAuto Scalingグループ(このまま入力)
- TARGET_GROUP_NAME…デプロイ対象のターゲットグループ(このまま入力)
- ACCOUNT_ID…現在構築を行っているAWSのアカウントID(このまま入力)
GROUP_NAME=${PROJECT_NAME}-deploygroup-blue-green APP_NAME=${PROJECT_NAME}-codedeploy-app ASG_NAME=${PROJECT_NAME}-asg TARGET_GROUP_NAME=${PROJECT_NAME}-tg ACCOUNT_ID=`aws sts get-caller-identity --query 'Account' --output text` ROLE_ARN=arn:aws:iam::${ACCOUNT_ID}:role/${PROJECT_NAME}-codedeploy-role
セットした内容を確認します。
cat << ETX GROUP_NAME : ${GROUP_NAME} APP_NAME : ${APP_NAME} ROLE_ARN : ${ROLE_ARN} ASG_NAME : ${ASG_NAME} TARGET_GROUP_NAME : ${TARGET_GROUP_NAME} ACCOUNT_ID : ${ACCOUNT_ID} ETX
デプロイグループを作成します。デプロイタイプはBlue/Greenで、成功後に置き換え前のインスタンスはすぐに削除されるようにしました。
aws deploy create-deployment-group \ --application-name ${APP_NAME} \ --deployment-group-name ${GROUP_NAME} \ --service-role-arn ${ROLE_ARN} \ --auto-scaling-groups ${ASG_NAME} \ --deployment-style deploymentType="BLUE_GREEN",deploymentOption="WITH_TRAFFIC_CONTROL" \ --blue-green-deployment-configuration terminateBlueInstancesOnDeploymentSuccess={action="TERMINATE"},deploymentReadyOption={actionOnTimeout=CONTINUE_DEPLOYMENT},greenFleetProvisioningOption={action=COPY_AUTO_SCALING_GROUP} \ --load-balancer-info targetGroupInfoList=[{name=${TARGET_GROUP_NAME}}]
コマンドの詳細については、以下を確認にしてください。
コマンドが正常に実行されるとdeploymentGroupId
が出力されます。
{ "deploymentGroupId": "fdd101f9-5c8b-4164-85a8-ad43eff90181" }
デプロイメントグループが作成されたことを確認します。
aws deploy list-deployment-groups --application-name ${APP_NAME}
正常に作成できていれば、指定した名称のデプロイメントグループが出力されます。
{ "deploymentGroups": [ "test-yotsugi-deploygroup-blue-green" ] }
リビジョン作成/アップロード
リビジョン(ソースコード/コンテンツ/実行ファイル等のアーカイブ)を作成します。リビジョンには、AppSpecファイル(デプロイの手順書)を含める必要があります。
ここでのAppSpecファイルはindex.html
を、Apacheのドキュメントルートにデプロイする内容としています。AppSpecファイルが格納してあるディレクトリに移動し、アーカイブします。
$ cd ../codedeploy/ $ zip -r revision.zip . adding: app/ (stored 0%) adding: app/index.html (deflated 17%) adding: appspec.yml (deflated 11%)
作成したリビジョンをリポジトリにアップロードします。ここでは、リポジトリにS3を利用しました。CodeDeployがサポートしているリポジトリについては、以下に記載あります。
$ aws s3 ls s3://${PROJECT_NAME}-bucket-${ACCOUNT_ID} $ aws s3 cp ./revision.zip s3://${PROJECT_NAME}-bucket-${ACCOUNT_ID} upload: ./revision.zip to s3://<PROJECT_NAME>-bucket-<ACCOUNT_ID>/revision.zip
正常にアップロードできたことを確認します。
$ aws s3 ls s3://${PROJECT_NAME}-bucket-${ACCOUNT_ID} 2019-04-11 19:44:38 1061 revision.zip
デプロイ実行
デプロイ実行前のWebコンテンツを確認します。ALBのDNS名にアクセスします。
Blue/Greenデプロイを実行します。
aws deploy create-deployment \ --application-name ${APP_NAME} \ --deployment-config-name CodeDeployDefault.AllAtOnce \ --deployment-group-name ${GROUP_NAME} \ --s3-location bundleType="zip",bucket=${PROJECT_NAME}-bucket-${ACCOUNT_ID},key=revision.zip \ --file-exists-behavior "OVERWRITE"
コマンドの詳細については、以下を確認にしてください。
コマンドが正常に実行されるとdeploymentId
が出力されます。
{ "deploymentId": "d-XRFTQUWJY" }
CodeDeployのコンソールより、デプロイの状態を確認してみます。「ステップ 1」では、Auto Scalingグループがコピーされ、EC2が起動します。
このステップが完了すると、指定したAuto Scalingグループがコピーされていることが確認できます。
EC2が新たに起動されています。
「ステップ 2」では、新たに起動されたEC2に、AppSpecファイルの定義にしたがいデプロイが実行されます。「ステップ 3」では、指定したターゲットグループ配下のEC2の置き換えが実施されます。
ターゲットグループ配下にEC2が追加されています。
デプロイの進捗により、登録済みターゲットのステータスが変化していきます。
このステップが完了すると、ターゲットグループ配下のEC2が置き換えられます。
「ステップ 4」では、置き換え前のリソースが削除されます。Auto Scalingグループ(EC2)の削除が行われています。
デプロイが完了しましたので、Webコンテンツを確認します。
Webコンテンツが置き換わっていることを確認できました。なお、デプロイでエラーになる場合は、以下を参考にログを確認してください。
さいごに
今回は環境構築をメインに書きました。次回は本エントリで作成した環境を利用し、Blue/Greenデプロイの動作について細かく確認したいと思います。